<html>
<head><meta charset="utf-8"><title>When to add #[inline]? · t-libs · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/index.html">t-libs</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html">When to add #[inline]?</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="187753679"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187753679" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Kalbertodt <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187753679">(Feb 09 2020 at 10:15)</a>:</h4>
<p>Do we have some clear rules when to add an <code>#[inline]</code> attribute to functions? <code>#[inline(always)]</code> and <code>#[inline(never)]</code> are only justified if there are good reasons (preferably benchmarks) to believe they improve performance/code size. The plain <code>#[inline]</code> on the other hand seems more confusing. "yes for non-generic functions", "sometimes also for generic functions", ...</p>
<p>Do we have a clear, precise guide on this?</p>



<a name="187760444"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187760444" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187760444">(Feb 09 2020 at 14:17)</a>:</h4>
<p>IIRC <span class="user-mention" data-user-id="116015">@Alex Crichton</span> was usually the go-to person on it, but we never wrote up clear guidelines.</p>
<p>My understanding is that:</p>
<ul>
<li><code>#[inline]</code> on a generic function is usually not the right idea, these are already available for inlining to LLVM</li>
<li><code>#[inline]</code> on a non-generic function makes it available for inlining to LLVM by codegening into downstream modules (i.e., has compile time overheads</li>
<li><code>#[inline(always)]</code> should pretty much never be used, at least in std, as it can bloat binaries and we usually don't know our downstream users that well (unlike downstream crates, where they might know that some function is only used in one place and should get inlined).</li>
<li><code>#[inline(never)]</code> should also pretty much never be used in std, for similar reasons; modulo e.g. panic machinery where we mark it <code>#[cold]</code> and <code>#[inline(never)]</code> often.</li>
</ul>



<a name="187763167"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187763167" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Steven Fackler <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187763167">(Feb 09 2020 at 15:51)</a>:</h4>
<p>IIRC <code>#[inline]</code> does increase the inlining priority of a generic function, so it can make sense to use there in some contexts, but you'd generally better have a good reason to do it.</p>



<a name="187763639"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187763639" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187763639">(Feb 09 2020 at 16:04)</a>:</h4>
<p>Yes, it does. But usually we want to leave it to LLVM to decide that in std, at least, since it "knows better" in some sense -- mostly I think because std is used in everyone's code, so we need to be careful about things more so than random libraries</p>



<a name="187766537"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187766537" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187766537">(Feb 09 2020 at 17:40)</a>:</h4>
<p>IIRC alex also based that advice on the idea that everyone will just use LTO all the time, which the default cargo profile.release doesn't actually do.</p>



<a name="187766618"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187766618" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187766618">(Feb 09 2020 at 17:44)</a>:</h4>
<p>thinlto is enabled by default</p>



<a name="187766645"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187766645" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187766645">(Feb 09 2020 at 17:44)</a>:</h4>
<p>you don't need full lto for these benefits afaik</p>



<a name="187766648"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187766648" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187766648">(Feb 09 2020 at 17:44)</a>:</h4>
<p>and it's fine for us to be not at 100% perf due to missing annotations if lto is not enabled</p>



<a name="187766650"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187766650" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187766650">(Feb 09 2020 at 17:44)</a>:</h4>
<p>people who want 100% perf imo should be using a custom profile and possibly even -Zbuild-std and so forth</p>



<a name="187766998"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187766998" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187766998">(Feb 09 2020 at 17:57)</a>:</h4>
<p>The documentation states that thinlto is only between codegen units, not between crates.</p>



<a name="187767117"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187767117" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187767117">(Feb 09 2020 at 18:01)</a>:</h4>
<p>that's true, but generics and #[inline] things get codegen'd into your crate</p>



<a name="187772062"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187772062" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Tim Vermeulen <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187772062">(Feb 09 2020 at 20:44)</a>:</h4>
<p>So for generic function <code>#[inline]</code> increases the inlining priority, but it still doesn't force it to be inlined? I used to think that <code>#[inline]</code> on a generic function did nothing, but I could have misunderstood</p>



<a name="187772580"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187772580" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Simon Sapin <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187772580">(Feb 09 2020 at 21:01)</a>:</h4>
<p>My understanding is that it also boosts some LLVM heuristic</p>



<a name="187772963"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187772963" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187772963">(Feb 09 2020 at 21:13)</a>:</h4>
<p>Yes, it both makes the item available for inlining (already true of generics) and bosts an llvm heuristic</p>



<a name="187774021"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187774021" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Hanna Kruppe <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187774021">(Feb 09 2020 at 21:45)</a>:</h4>
<p>However, also keep in mind that rustc's codegen strategies have become more nuanced over time. For example, there's now a mode (-Zshare-generics) that reuses monomorphizations already created in dependencies where possible, though it's only enabled by default at opt-level={0,1,s,z} today. So the old heuristic "generic = available for inlining everywhere" no longer necessarily holds.</p>



<a name="187818240"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187818240" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187818240">(Feb 10 2020 at 14:11)</a>:</h4>
<p>Yes, I think we don't care about non-opt-level=3 performance <em>that</em> much, in practice, but that's definitely true :)</p>



<a name="187831451"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187831451" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Alex Crichton <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187831451">(Feb 10 2020 at 16:26)</a>:</h4>
<p>The last I wrote up (I think?) about inlining stuff is at <a href="https://github.com/rust-lang/hashbrown/pull/119" target="_blank" title="https://github.com/rust-lang/hashbrown/pull/119">https://github.com/rust-lang/hashbrown/pull/119</a>. Basically what was said previously is correct. You never need <code>#[inline(always)]</code> unless it's like an ABI thing. You probably don't ever need <code>#[inline(never)]</code> unless you actually see LLVM making wrong decisions (we could probably remove <code>#[inline(never)]</code> from <code>#[cold]</code> functions, those attributes are likely basically synonymous). You also basically never need <code>#[inline]</code> unless benchmarks show differently.</p>
<p>There's legitimate cases you need <code>#[inline]</code> such as tiny functions that aren't otherwise inlined, but I'd still recommend waiting for a benchmark to show anything before actually applying <code>#[inline]</code>. The downside of <code>#[inline]</code> is that increases compile times, and if you add it <em>everywhere</em> it can actually lead to very noticeable increases in compile time.</p>



<a name="187832459"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187832459" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> XAMPPRocky <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187832459">(Feb 10 2020 at 16:37)</a>:</h4>
<p>There is documentation that KodrAus added to the libs team docs on forge, I don't how much of that matches the current discussion though. <a href="https://forge.rust-lang.org/libs/maintaining-std.html#is-that-inline-right" target="_blank" title="https://forge.rust-lang.org/libs/maintaining-std.html#is-that-inline-right">https://forge.rust-lang.org/libs/maintaining-std.html#is-that-inline-right</a></p>



<a name="187902819"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187902819" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Elichai Turkel <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187902819">(Feb 11 2020 at 11:15)</a>:</h4>
<p><span class="user-mention" data-user-id="116015">@Alex Crichton</span> So why almost all the user facing functions in std have inline attributes?</p>



<a name="187907408"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187907408" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187907408">(Feb 11 2020 at 12:36)</a>:</h4>
<p>Many of them were likely added from benchmarks, though some look to be at least plausibly wrong</p>



<a name="187934281"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187934281" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Alex Crichton <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187934281">(Feb 11 2020 at 17:38)</a>:</h4>
<p><span class="user-mention" data-user-id="249222">@Elichai Turkel</span> agreed with <span class="user-mention" data-user-id="116122">@simulacrum</span>, they're probably either erroneous, justified by a benchmark since forgotten, or added at a time it was more necessary than it is today. Consistency is definitely not a quality anyone would label libstd's usage of <code>#[inline]</code> as</p>



<a name="187935570"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187935570" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187935570">(Feb 11 2020 at 17:52)</a>:</h4>
<p>There are times when even debug performance can also be a concern, perhaps some of them are from that.</p>



<a name="187954367"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187954367" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Simon Sapin <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187954367">(Feb 11 2020 at 21:00)</a>:</h4>
<p>Does <code>#[inline]</code> do anything with <code>opt-level=0</code>?</p>



<a name="187954639"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187954639" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187954639">(Feb 11 2020 at 21:02)</a>:</h4>
<p>We explicitly currently do not optimize for debug performance in the standard library, generally speaking.</p>
<p>I am not sure about opt-level=0 and inline.</p>



<a name="187955298"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187955298" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Hanna Kruppe <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187955298">(Feb 11 2020 at 21:07)</a>:</h4>
<p>opt-level=0 doesn't run the inlining pass (only AlwaysInliner), but I believe it still <em>in general</em> has to codegen inline functions in crates using them, so code size and build times get worse for no benefit. Maybe upstream instances can be reused, if they exist and are exported, but as one often links release builds of libstd, libcore, etc. and copies of inline functions are internalized in normal release mode...</p>



<a name="187959029"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187959029" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187959029">(Feb 11 2020 at 21:42)</a>:</h4>
<p>Hmm, unfortunate</p>



<a name="187968842"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/When%20to%20add%20%23%5Binline%5D%3F/near/187968842" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Alex Crichton <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/When.20to.20add.20.23.5Binline.5D.3F.html#187968842">(Feb 11 2020 at 23:53)</a>:</h4>
<p><span class="user-mention" data-user-id="219747">@Simon Sapin</span> in <code>opt-level=0</code> mode as <span class="user-mention" data-user-id="124289">@Hanna Kruppe</span> pointed out the inliner isn't even run, but the <code>inlinehint</code> LLVM attribute <a href="https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2018&amp;gist=b10ec97edc60b0634bfc06cea9e1cdf8" target="_blank" title="https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2018&amp;gist=b10ec97edc60b0634bfc06cea9e1cdf8">is indeed added</a>. Additionally in release mode <code>#[inline]</code> causes translation into every single CGU, whereas in debug mode <a href="https://github.com/rust-lang/rust/blob/3f32e3001e3a64c1baa509d3d1734dff53f14d81/src/librustc/mir/mono.rs#L87" target="_blank" title="https://github.com/rust-lang/rust/blob/3f32e3001e3a64c1baa509d3d1734dff53f14d81/src/librustc/mir/mono.rs#L87">we do not do that and only translate into one CGU</a>. Effectively, it's entirely ignored. (this is distinct from <code>#[inline(always)]</code>)</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>